package com.chenqq.camerademo.camera.widget;

import android.content.Context;
import android.graphics.SurfaceTexture;
import android.hardware.usb.UsbDevice;
import android.nfc.Tag;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.Surface;
import android.widget.FrameLayout;

import com.chenqq.camerademo.camera.field.Field_Camera_Parameter;
import com.chenqq.camerademo.camera.handler.AbstractUVCCameraHandler;
import com.chenqq.camerademo.camera.handler.UVCCameraHandler;
import com.chenqq.camerademo.camera.helper.CameraUnits;
import com.chenqq.camerademo.camera.helper.UsbHelperTools;
import com.chenqq.camerademo.camera.usb.UsbControlBlock;
import com.chenqq.camerademo.camera.usbInterface.OnDeviceConnectListener;
import com.chenqq.camerademo.camera.utils.FileUtils;
import com.chenqq.camerademo.camera.uvc.RecordParams;

import org.easydarwin.sw.TxtOverlay;

import java.io.File;
import java.io.IOException;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class CameraView extends FrameLayout implements
        OnDeviceConnectListener, CameraViewInterface.Callback {

    private UVCCameraTextureView cameraTextureView;
    private boolean isRequest;
    private boolean isPreview;
    private int previewWidth = Field_Camera_Parameter.DEFAULT_PREVIEW_WIDTH;
    private int previewHeight = Field_Camera_Parameter.DEFAULT_PREVIEW_HEIGHT;
    private int mFrameFormat = Field_Camera_Parameter.FRAME_FORMAT_MJPEG;

    public static final String SUFFIX_JPEG = ".jpg";
    public static final String SUFFIX_MP4 = ".mp4";
    private UVCCameraHandler mCameraHandler;
    private Handler handler = new Handler(Looper.getMainLooper());
    private UsbControlBlock mCtrlBlock;
    private AbstractUVCCameraHandler.OnPreViewResultListener onPreViewResultListener;

    public CameraView(@NonNull Context context) {
        this(context, null);
    }

    public CameraView(@NonNull Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CameraView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context);
    }

    private void initView(Context context) {
        if (cameraTextureView != null) {
            cameraTextureView.onPause();
            removeView(cameraTextureView);
            cameraTextureView = null;
        }
        if (mCameraHandler != null) {
            mCameraHandler.release();
            mCameraHandler = null;
        }
        cameraTextureView = new UVCCameraTextureView(context);
        LayoutParams layoutParams = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
        layoutParams.gravity = Gravity.CENTER;
        addView(cameraTextureView, layoutParams);
        CameraUnits.getInStance().setOnDeviceConnectListener(this);
        createUVCCamera();
    }

    public void setOnPreViewResultListener(AbstractUVCCameraHandler.OnPreViewResultListener onPreViewResultListener) {
        this.onPreViewResultListener = onPreViewResultListener;
        if (mCameraHandler != null) {
            mCameraHandler.setOnPreViewResultListener(this.onPreViewResultListener);
        }
    }

    private void createUVCCamera() {
        cameraTextureView.setCallback(this);
        cameraTextureView.setAspectRatio(previewWidth / (float) previewHeight);
        mCameraHandler = UVCCameraHandler.createHandler(getContext(),
                cameraTextureView, 2,
                previewWidth, previewHeight, mFrameFormat);
        mCameraHandler.setOnPreViewResultListener(onPreViewResultListener == null
                ? new AbstractUVCCameraHandler.OnPreViewResultListener() {
            @Override
            public void onPreviewResult(byte[] data) {
//                Log.i("数据矩阵",data.length+" ["+data+"]");
            }
        } : onPreViewResultListener);

    }

    public void closeCamera() {
        if (mCameraHandler != null) {
            mCameraHandler.close();
            mCameraHandler.release();
            mCameraHandler = null;
        }

    }

    @Override
    public void onConnect(String Tag, UsbDevice device, UsbControlBlock ctrlBlock, boolean createNew) {
        if (mCtrlBlock != null&&!mCtrlBlock.getDeviceName().equals(ctrlBlock.getDeviceName())) {
            closeCamera();
            mCtrlBlock = null;
        }
        if (mCameraHandler==null){
           createUVCCamera();
        }
        mCtrlBlock = ctrlBlock;
        Log.e("onConnect", "onConnect: " + ctrlBlock.getDeviceName());
        openCamera(ctrlBlock);
        isRequest = true;
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                startPreview(cameraTextureView);
            }
        }, 500);
    }

    @Override
    public void onDisconnect(UsbDevice device, UsbControlBlock ctrlBlock) {
        Log.e("onDisconnect", "onDisconnect: " + ctrlBlock.getDeviceName());
        if (mCtrlBlock != null && mCtrlBlock.getDeviceName().equals(ctrlBlock.getDeviceName())) {
            if (isRequest) {
                isRequest = false;
                closeCamera();
                stopPreview();
            }
        }
//        UsbHelperTools.getInStance().checkStart();
    }

    @Override
    public void onCancel(UsbDevice device) {
        if (mCtrlBlock != null) {
            stopPreview();
            closeCamera();
            mCtrlBlock = null;
        }
    }

    private void openCamera(UsbControlBlock ctrlBlock) {
        if (mCameraHandler != null) {
            mCameraHandler.open(ctrlBlock);
        }
    }

    private void startPreview(CameraViewInterface cameraView) {
        SurfaceTexture st = cameraView.getSurfaceTexture();
        if (mCameraHandler != null) {
            mCameraHandler.startPreview(st);
        }
        isPreview = true;
    }

    private void stopPreview() {
        if (mCameraHandler != null) {
            mCameraHandler.stopPreview();
        }
        isPreview = false;
    }

    /**
     * 设置亮度
     *
     * @param progress
     */
    public void setBrightness(int progress) {
        if (mCameraHandler != null && isCameraOpened()) {
            setModelValue(Field_Camera_Parameter.PU_BRIGHTNESS, progress);
        }
    }

    /**
     * 设置对比度
     *
     * @param progress
     */
    public void setContrast(int progress) {
        if (mCameraHandler != null && isCameraOpened()) {
            setModelValue(Field_Camera_Parameter.PU_CONTRAST, progress);
        }
    }

    public boolean isCameraOpened() {
        if (mCameraHandler != null) {
            return mCameraHandler.isOpened();
        }
        return false;
    }

    private boolean checkSupportFlag(final int flag) {
        return mCameraHandler != null && mCameraHandler.checkSupportFlag(flag);
    }

    private int getModelValue(final int flag) {
        return mCameraHandler != null ? mCameraHandler.getValue(flag) : 0;
    }

    private int setModelValue(final int flag, final int value) {
        return mCameraHandler != null ? mCameraHandler.setValue(flag, value) : 0;
    }

    private int resetModelValue(final int flag) {
        return mCameraHandler != null ? mCameraHandler.resetValue(flag) : 0;
    }

    private void startCameraFoucs() {
        if (mCameraHandler != null) {
            mCameraHandler.startCameraFoucs();
        }
    }

    public void setDefaultPreviewSize(int defaultWidth, int defaultHeight) {
        if (previewWidth == defaultWidth && previewHeight == defaultHeight) {
            return;
        }
        this.previewWidth = defaultWidth;
        this.previewHeight = defaultHeight;
        if (!isPreview) {
            Log.i("isPreview", "isPreview=" + isPreview);
            return;
        }
        if (mCameraHandler != null) {
            mCameraHandler.release();
            mCameraHandler = null;
        }
        cameraTextureView.setAspectRatio(previewWidth / (float) previewHeight);
        mCameraHandler = UVCCameraHandler.createHandler(getContext(), cameraTextureView
                , 2, previewWidth, previewHeight, mFrameFormat);
        openCamera(mCtrlBlock);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                startPreview(cameraTextureView);
            }
        }, 500);
    }

    /**
     * 截图
     *
     * @param patch
     * @param onCaptureListener
     */
    public void capturePicture(String patch, AbstractUVCCameraHandler.OnCaptureListener onCaptureListener) {
        if (TextUtils.isEmpty(patch)) {
            patch = getContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
                    .getAbsolutePath() + "/picture/";

        }
        File file = new File(patch);
        if (!file.exists()) {
            boolean mkdirs = file.mkdirs();
        }
        File pathfile = new File(file, System.currentTimeMillis() + SUFFIX_JPEG);
        if (!pathfile.exists()) {
            try {
                boolean newFile = pathfile.createNewFile();
            } catch (IOException exception) {
                Log.e("截图失败", "capturePicture: "+exception );
                exception.printStackTrace();
            }
        }
        mCameraHandler.captureStill(pathfile.getAbsolutePath(), onCaptureListener == null ?
                new AbstractUVCCameraHandler.OnCaptureListener() {
                    @Override
                    public void onCaptureResult(String picPath) {
                        Log.i("截图", "onCaptureResult: " + picPath);
                    }
                } : onCaptureListener);

    }

    /**
     * 开始录制
     *
     * @param path
     * @param onEncodeResultListener
     */
    public void startRecord(String path, AbstractUVCCameraHandler.OnEncodeResultListener onEncodeResultListener) {
        if (mCameraHandler == null || !isCameraOpened()) {
            UsbHelperTools.getInStance().checkStart();
            Log.e("录制错误", "startRecord: sorry,camera open failed" + " isCameraOpened== " + isCameraOpened());
            return;
        }
        if (isPushing()) {
            FileUtils.releaseFile();
            stopPusher();
            return;
        }
        if (TextUtils.isEmpty(path)) {
            path = getContext().getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS)
                    .getAbsolutePath() + "/video/" + System.currentTimeMillis();
        }
        RecordParams params = new RecordParams();
        params.setRecordPath(path);
        params.setRecordDuration(0);                        // auto divide saved,default 0 means not divided
        params.setVoiceClose(false);
        params.setSupportOverlay(true);
        startPusher(params, onEncodeResultListener == null ?
                new AbstractUVCCameraHandler.OnEncodeResultListener() {
                    @Override
                    public void onEncodeResult(byte[] data, int offset, int length, long timestamp, int type) {
                        if (type == 1) {
                            FileUtils.putFileStream(data, offset, length);
                        }
                    }

                    @Override
                    public void onRecordResult(String videoPath) {
                        Log.i("录制视频", "onRecordResult: " + videoPath);
                    }
                } : onEncodeResultListener);
        startCameraFoucs();
    }


    private void startPusher(RecordParams params, AbstractUVCCameraHandler.OnEncodeResultListener listener) {
        if (mCameraHandler != null && !isPushing()) {
            if (params.isSupportOverlay()) {
                TxtOverlay.install(getContext().getApplicationContext());
            }
            mCameraHandler.startRecording(params, listener);
        }
    }

    public void stopPusher() {
        if (mCameraHandler != null && isPushing()) {
            mCameraHandler.stopRecording();
        }
    }

    public boolean isPushing() {
        if (mCameraHandler != null) {
            return mCameraHandler.isRecording();
        }
        return false;
    }

    @Override
    public void onSurfaceCreated(CameraViewInterface view, Surface surface) {
        if (!isPreview && isCameraOpened()) {
            startPreview(cameraTextureView);
            isPreview = true;
        }
    }

    @Override
    public void onSurfaceChanged(CameraViewInterface view, Surface surface, int width, int height) {

    }

    @Override
    public void onSurfaceDestroy(CameraViewInterface view, Surface surface) {
        if (isPreview && isCameraOpened()) {
            stopPreview();
            isPreview = false;
        }
    }
}
